Section II Q-4: Telephony API / Canvas Drawing Application (5 Marks)
Question
i) Create an Android application that uses the Telephony API to get the device's network information.
ii) Create an Android application that uses Canvas to draw shapes and text.
Answer
i) Telephony API Network Information Application
This application demonstrates how to use the Telephony API to retrieve and display comprehensive network information.
AndroidManifest.xml Permissions
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.telephonyapi">
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".NetworkInfoActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Main Activity Layout (activity_network_info.xml)
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Network Information"
android:textSize="24sp"
android:textStyle="bold"
android:layout_gravity="center"
android:layout_marginBottom="24dp" />
<Button
android:id="@+id/btnGetNetworkInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Get Network Information"
android:layout_marginBottom="16dp" />
<Button
android:id="@+id/btnRefresh"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Refresh Information"
android:layout_marginBottom="24dp" />
<!-- Device Information Card -->
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:cardCornerRadius="8dp"
android:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Device Information"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginBottom="12dp" />
<TextView
android:id="@+id/tvDeviceInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Device info will appear here..."
android:textSize="14sp"
android:fontFamily="monospace" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Network Information Card -->
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:cardCornerRadius="8dp"
android:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Network Information"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginBottom="12dp" />
<TextView
android:id="@+id/tvNetworkInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Network info will appear here..."
android:textSize="14sp"
android:fontFamily="monospace" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- SIM Information Card -->
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:cardCornerRadius="8dp"
android:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SIM Information"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginBottom="12dp" />
<TextView
android:id="@+id/tvSimInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="SIM info will appear here..."
android:textSize="14sp"
android:fontFamily="monospace" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
</ScrollView>
NetworkInfoActivity.java
package com.example.telephonyapi;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.telephony.CellInfo;
import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellInfoWcdma;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.util.List;
public class NetworkInfoActivity extends AppCompatActivity {
private static final int PERMISSION_REQUEST_CODE = 1000;
private TelephonyManager telephonyManager;
private PhoneStateListener phoneStateListener;
private TextView tvDeviceInfo, tvNetworkInfo, tvSimInfo;
private Button btnGetNetworkInfo, btnRefresh;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_network_info);
initializeViews();
initializeTelephonyManager();
setupClickListeners();
if (checkPermissions()) {
getNetworkInformation();
} else {
requestPermissions();
}
}
private void initializeViews() {
tvDeviceInfo = findViewById(R.id.tvDeviceInfo);
tvNetworkInfo = findViewById(R.id.tvNetworkInfo);
tvSimInfo = findViewById(R.id.tvSimInfo);
btnGetNetworkInfo = findViewById(R.id.btnGetNetworkInfo);
btnRefresh = findViewById(R.id.btnRefresh);
}
private void initializeTelephonyManager() {
telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
// Create phone state listener for dynamic updates
phoneStateListener = new PhoneStateListener() {
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
updateSignalStrength(signalStrength);
}
@Override
public void onServiceStateChanged(ServiceState serviceState) {
super.onServiceStateChanged(serviceState);
updateServiceState(serviceState);
}
};
}
private void setupClickListeners() {
btnGetNetworkInfo.setOnClickListener(v -> {
if (checkPermissions()) {
getNetworkInformation();
} else {
requestPermissions();
}
});
btnRefresh.setOnClickListener(v -> {
if (checkPermissions()) {
getNetworkInformation();
Toast.makeText(this, "Information refreshed", Toast.LENGTH_SHORT).show();
}
});
}
private void getNetworkInformation() {
if (!checkPermissions()) {
return;
}
getDeviceInformation();
getNetworkDetails();
getSimInformation();
}
@SuppressWarnings("MissingPermission")
private void getDeviceInformation() {
StringBuilder deviceInfo = new StringBuilder();
try {
// Device ID and IMEI
String deviceId = telephonyManager.getDeviceId();
String imei = telephonyManager.getImei();
// Phone type
int phoneType = telephonyManager.getPhoneType();
String phoneTypeStr = getPhoneTypeString(phoneType);
// Software version
String softwareVersion = telephonyManager.getDeviceSoftwareVersion();
deviceInfo.append("Device ID: ").append(deviceId != null ? deviceId : "N/A").append("\n");
deviceInfo.append("IMEI: ").append(imei != null ? imei : "N/A").append("\n");
deviceInfo.append("Phone Type: ").append(phoneTypeStr).append("\n");
deviceInfo.append("Software Version: ").append(softwareVersion != null ? softwareVersion : "N/A").append("\n");
// Additional device info
deviceInfo.append("Has ICC Card: ").append(telephonyManager.hasIccCard()).append("\n");
deviceInfo.append("Is Network Roaming: ").append(telephonyManager.isNetworkRoaming()).append("\n");
} catch (SecurityException e) {
deviceInfo.append("Permission denied for device information\n");
}
tvDeviceInfo.setText(deviceInfo.toString());
}
@SuppressWarnings("MissingPermission")
private void getNetworkDetails() {
StringBuilder networkInfo = new StringBuilder();
try {
// Network operator information
String networkOperator = telephonyManager.getNetworkOperator();
String networkOperatorName = telephonyManager.getNetworkOperatorName();
String networkCountryIso = telephonyManager.getNetworkCountryIso();
// Network type
int networkType = telephonyManager.getNetworkType();
String networkTypeStr = getNetworkTypeString(networkType);
// Data state
int dataState = telephonyManager.getDataState();
String dataStateStr = getDataStateString(dataState);
// Call state
int callState = telephonyManager.getCallState();
String callStateStr = getCallStateString(callState);
networkInfo.append("Network Operator: ").append(networkOperator).append("\n");
networkInfo.append("Operator Name: ").append(networkOperatorName).append("\n");
networkInfo.append("Country ISO: ").append(networkCountryIso).append("\n");
networkInfo.append("Network Type: ").append(networkTypeStr).append("\n");
networkInfo.append("Data State: ").append(dataStateStr).append("\n");
networkInfo.append("Call State: ").append(callStateStr).append("\n");
// Cell information
List<CellInfo> cellInfoList = telephonyManager.getAllCellInfo();
if (cellInfoList != null && !cellInfoList.isEmpty()) {
networkInfo.append("\nCell Information:\n");
for (int i = 0; i < cellInfoList.size(); i++) {
CellInfo cellInfo = cellInfoList.get(i);
networkInfo.append("Cell ").append(i + 1).append(": ");
networkInfo.append(getCellInfoString(cellInfo)).append("\n");
}
}
} catch (SecurityException e) {
networkInfo.append("Permission denied for network information\n");
}
tvNetworkInfo.setText(networkInfo.toString());
}
@SuppressWarnings("MissingPermission")
private void getSimInformation() {
StringBuilder simInfo = new StringBuilder();
try {
// SIM state
int simState = telephonyManager.getSimState();
String simStateStr = getSimStateString(simState);
// SIM operator information
String simOperator = telephonyManager.getSimOperator();
String simOperatorName = telephonyManager.getSimOperatorName();
String simCountryIso = telephonyManager.getSimCountryIso();
String simSerialNumber = telephonyManager.getSimSerialNumber();
// Subscriber information
String subscriberId = telephonyManager.getSubscriberId();
String line1Number = telephonyManager.getLine1Number();
simInfo.append("SIM State: ").append(simStateStr).append("\n");
simInfo.append("SIM Operator: ").append(simOperator).append("\n");
simInfo.append("SIM Operator Name: ").append(simOperatorName).append("\n");
simInfo.append("SIM Country ISO: ").append(simCountryIso).append("\n");
simInfo.append("SIM Serial Number: ").append(simSerialNumber != null ? simSerialNumber : "N/A").append("\n");
simInfo.append("Subscriber ID: ").append(subscriberId != null ? subscriberId : "N/A").append("\n");
simInfo.append("Phone Number: ").append(line1Number != null ? line1Number : "N/A").append("\n");
} catch (SecurityException e) {
simInfo.append("Permission denied for SIM information\n");
}
tvSimInfo.setText(simInfo.toString());
}
private void updateSignalStrength(SignalStrength signalStrength) {
// Update signal strength information in real-time
String signalInfo = "Signal Strength Level: " + signalStrength.getLevel() + "/4\n";
// Add to existing network info
}
private void updateServiceState(ServiceState serviceState) {
// Update service state information
String serviceInfo = "Service State: " + getServiceStateString(serviceState.getState()) + "\n";
// Add to existing network info
}
// Helper methods to convert constants to readable strings
private String getPhoneTypeString(int phoneType) {
switch (phoneType) {
case TelephonyManager.PHONE_TYPE_NONE: return "None";
case TelephonyManager.PHONE_TYPE_GSM: return "GSM";
case TelephonyManager.PHONE_TYPE_CDMA: return "CDMA";
case TelephonyManager.PHONE_TYPE_SIP: return "SIP";
default: return "Unknown";
}
}
private String getNetworkTypeString(int networkType) {
switch (networkType) {
case TelephonyManager.NETWORK_TYPE_UNKNOWN: return "Unknown";
case TelephonyManager.NETWORK_TYPE_GPRS: return "GPRS";
case TelephonyManager.NETWORK_TYPE_EDGE: return "EDGE";
case TelephonyManager.NETWORK_TYPE_UMTS: return "UMTS";
case TelephonyManager.NETWORK_TYPE_HSDPA: return "HSDPA";
case TelephonyManager.NETWORK_TYPE_HSUPA: return "HSUPA";
case TelephonyManager.NETWORK_TYPE_HSPA: return "HSPA";
case TelephonyManager.NETWORK_TYPE_LTE: return "LTE";
case TelephonyManager.NETWORK_TYPE_NR: return "5G NR";
default: return "Unknown (" + networkType + ")";
}
}
private String getDataStateString(int dataState) {
switch (dataState) {
case TelephonyManager.DATA_DISCONNECTED: return "Disconnected";
case TelephonyManager.DATA_CONNECTING: return "Connecting";
case TelephonyManager.DATA_CONNECTED: return "Connected";
case TelephonyManager.DATA_SUSPENDED: return "Suspended";
default: return "Unknown";
}
}
private String getCallStateString(int callState) {
switch (callState) {
case TelephonyManager.CALL_STATE_IDLE: return "Idle";
case TelephonyManager.CALL_STATE_RINGING: return "Ringing";
case TelephonyManager.CALL_STATE_OFFHOOK: return "Off Hook";
default: return "Unknown";
}
}
private String getSimStateString(int simState) {
switch (simState) {
case TelephonyManager.SIM_STATE_UNKNOWN: return "Unknown";
case TelephonyManager.SIM_STATE_ABSENT: return "Absent";
case TelephonyManager.SIM_STATE_PIN_REQUIRED: return "PIN Required";
case TelephonyManager.SIM_STATE_PUK_REQUIRED: return "PUK Required";
case TelephonyManager.SIM_STATE_NETWORK_LOCKED: return "Network Locked";
case TelephonyManager.SIM_STATE_READY: return "Ready";
default: return "Unknown";
}
}
private String getServiceStateString(int serviceState) {
switch (serviceState) {
case ServiceState.STATE_IN_SERVICE: return "In Service";
case ServiceState.STATE_OUT_OF_SERVICE: return "Out of Service";
case ServiceState.STATE_EMERGENCY_ONLY: return "Emergency Only";
case ServiceState.STATE_POWER_OFF: return "Power Off";
default: return "Unknown";
}
}
private String getCellInfoString(CellInfo cellInfo) {
if (cellInfo instanceof CellInfoGsm) {
return "GSM Cell";
} else if (cellInfo instanceof CellInfoLte) {
return "LTE Cell";
} else if (cellInfo instanceof CellInfoWcdma) {
return "WCDMA Cell";
} else {
return "Unknown Cell Type";
}
}
private boolean checkPermissions() {
return ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
== PackageManager.PERMISSION_GRANTED;
}
private void requestPermissions() {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_COARSE_LOCATION},
PERMISSION_REQUEST_CODE);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getNetworkInformation();
Toast.makeText(this, "Permissions granted", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Permissions required for network information",
Toast.LENGTH_LONG).show();
}
}
}
@Override
protected void onResume() {
super.onResume();
if (checkPermissions()) {
telephonyManager.listen(phoneStateListener,
PhoneStateListener.LISTEN_SIGNAL_STRENGTHS |
PhoneStateListener.LISTEN_SERVICE_STATE);
}
}
@Override
protected void onPause() {
super.onPause();
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
}
}
ii) Canvas Drawing Shapes and Text Application
This application demonstrates comprehensive Canvas drawing capabilities including shapes, text, and interactive drawing.
Canvas Drawing Layout (activity_canvas_drawing.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- Control Panel -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp"
android:background="#F0F0F0">
<Button
android:id="@+id/btnClear"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Clear"
android:layout_margin="2dp" />
<Button
android:id="@+id/btnShapes"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Shapes"
android:layout_margin="2dp" />
<Button
android:id="@+id/btnText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Text"
android:layout_margin="2dp" />
<Button
android:id="@+id/btnColors"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Colors"
android:layout_margin="2dp" />
</LinearLayout>
<!-- Drawing Canvas -->
<com.example.canvasdrawing.DrawingView
android:id="@+id/drawingView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#FFFFFF" />
<!-- Info Panel -->
<TextView
android:id="@+id/tvInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Tap to draw, use buttons to change modes"
android:textSize="14sp"
android:padding="8dp"
android:background="#E0E0E0"
android:gravity="center" />
</LinearLayout>
Custom Drawing View (DrawingView.java)
package com.example.canvasdrawing;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
public class DrawingView extends View {
private Paint drawPaint, canvasPaint;
private Canvas drawCanvas;
private Bitmap canvasBitmap;
private int currentColor = Color.BLACK;
private float brushSize = 10f;
private DrawingMode currentMode = DrawingMode.FREE_DRAW;
private Path drawPath;
private List<DrawingObject> drawingObjects;
private float startX, startY, endX, endY;
private boolean isDrawing = false;
public enum DrawingMode {
FREE_DRAW, RECTANGLE, CIRCLE, LINE, TEXT
}
private static class DrawingObject {
Path path;
Paint paint;
DrawingMode mode;
String text;
float x, y;
RectF bounds;
DrawingObject(DrawingMode mode) {
this.mode = mode;
this.paint = new Paint();
}
}
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
setupDrawing();
}
private void setupDrawing() {
drawPath = new Path();
drawingObjects = new ArrayList<>();
drawPaint = new Paint();
drawPaint.setColor(currentColor);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(brushSize);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
// Draw initial content
drawInitialContent();
}
private void drawInitialContent() {
// Draw background grid
Paint gridPaint = new Paint();
gridPaint.setColor(Color.LTGRAY);
gridPaint.setStrokeWidth(1);
gridPaint.setAlpha(50);
int gridSize = 50;
for (int i = 0; i < getWidth(); i += gridSize) {
drawCanvas.drawLine(i, 0, i, getHeight(), gridPaint);
}
for (int i = 0; i < getHeight(); i += gridSize) {
drawCanvas.drawLine(0, i, getWidth(), i, gridPaint);
}
// Draw sample shapes and text
drawSampleContent();
}
private void drawSampleContent() {
Paint samplePaint = new Paint();
samplePaint.setAntiAlias(true);
// Draw title
samplePaint.setColor(Color.BLUE);
samplePaint.setTextSize(60);
samplePaint.setTextAlign(Paint.Align.CENTER);
drawCanvas.drawText("Canvas Drawing Demo", getWidth() / 2f, 80, samplePaint);
// Draw shapes with different colors and styles
// Rectangle
samplePaint.setColor(Color.RED);
samplePaint.setStyle(Paint.Style.FILL);
drawCanvas.drawRect(50, 120, 200, 220, samplePaint);
// Circle
samplePaint.setColor(Color.GREEN);
samplePaint.setStyle(Paint.Style.STROKE);
samplePaint.setStrokeWidth(8);
drawCanvas.drawCircle(300, 170, 50, samplePaint);
// Triangle using Path
samplePaint.setColor(Color.MAGENTA);
samplePaint.setStyle(Paint.Style.FILL);
Path triangle = new Path();
triangle.moveTo(450, 120);
triangle.lineTo(400, 220);
triangle.lineTo(500, 220);
triangle.close();
drawCanvas.drawPath(triangle, samplePaint);
// Oval
samplePaint.setColor(Color.CYAN);
samplePaint.setStyle(Paint.Style.FILL_AND_STROKE);
samplePaint.setStrokeWidth(4);
RectF oval = new RectF(50, 260, 200, 340);
drawCanvas.drawOval(oval, samplePaint);
// Rounded rectangle
samplePaint.setColor(Color.YELLOW);
RectF roundRect = new RectF(250, 260, 400, 340);
drawCanvas.drawRoundRect(roundRect, 20, 20, samplePaint);
// Arc
samplePaint.setColor(Color.parseColor("#FF6B35"));
RectF arcRect = new RectF(450, 260, 550, 340);
drawCanvas.drawArc(arcRect, 0, 270, true, samplePaint);
// Lines with different effects
samplePaint.setColor(Color.BLACK);
samplePaint.setStyle(Paint.Style.STROKE);
samplePaint.setStrokeWidth(5);
// Solid line
drawCanvas.drawLine(50, 380, 200, 380, samplePaint);
// Dashed line effect (multiple short lines)
for (int i = 250; i < 400; i += 15) {
drawCanvas.drawLine(i, 380, i + 10, 380, samplePaint);
}
// Text with different styles
samplePaint.setTextSize(32);
samplePaint.setColor(Color.BLUE);
drawCanvas.drawText("Bold Text", 50, 450, samplePaint);
samplePaint.setTextSize(24);
samplePaint.setColor(Color.RED);
samplePaint.setUnderlineText(true);
drawCanvas.drawText("Underlined Text", 250, 450, samplePaint);
samplePaint.setUnderlineText(false);
// Gradient text effect
samplePaint.setTextSize(28);
samplePaint.setColor(Color.GREEN);
samplePaint.setShadowLayer(5, 3, 3, Color.GRAY);
drawCanvas.drawText("Shadow Text", 50, 500, samplePaint);
samplePaint.clearShadowLayer();
// Instructions
samplePaint.setTextSize(20);
samplePaint.setColor(Color.DKGRAY);
drawCanvas.drawText("Touch and drag to draw!", 50, getHeight() - 50, samplePaint);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
// Draw current path for free drawing
if (currentMode == DrawingMode.FREE_DRAW) {
canvas.drawPath(drawPath, drawPaint);
}
// Draw preview for shape modes
if (isDrawing && currentMode != DrawingMode.FREE_DRAW) {
drawPreview(canvas);
}
}
private void drawPreview(Canvas canvas) {
Paint previewPaint = new Paint(drawPaint);
previewPaint.setAlpha(128); // Semi-transparent preview
switch (currentMode) {
case RECTANGLE:
canvas.drawRect(Math.min(startX, endX), Math.min(startY, endY),
Math.max(startX, endX), Math.max(startY, endY), previewPaint);
break;
case CIRCLE:
float radius = (float) Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2));
canvas.drawCircle(startX, startY, radius, previewPaint);
break;
case LINE:
canvas.drawLine(startX, startY, endX, endY, previewPaint);
break;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
handleTouchDown(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
handleTouchMove(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
handleTouchUp(touchX, touchY);
break;
default:
return false;
}
invalidate();
return true;
}
private void handleTouchDown(float x, float y) {
startX = x;
startY = y;
isDrawing = true;
if (currentMode == DrawingMode.FREE_DRAW) {
drawPath.reset();
drawPath.moveTo(x, y);
}
}
private void handleTouchMove(float x, float y) {
endX = x;
endY = y;
if (currentMode == DrawingMode.FREE_DRAW) {
drawPath.quadTo(startX, startY, (x + startX) / 2, (y + startY) / 2);
startX = x;
startY = y;
}
}
private void handleTouchUp(float x, float y) {
isDrawing = false;
endX = x;
endY = y;
switch (currentMode) {
case FREE_DRAW:
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
break;
case RECTANGLE:
drawCanvas.drawRect(Math.min(startX, endX), Math.min(startY, endY),
Math.max(startX, endX), Math.max(startY, endY), drawPaint);
break;
case CIRCLE:
float radius = (float) Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2));
drawCanvas.drawCircle(startX, startY, radius, drawPaint);
break;
case LINE:
drawCanvas.drawLine(startX, startY, endX, endY, drawPaint);
break;
case TEXT:
Paint textPaint = new Paint(drawPaint);
textPaint.setTextSize(40);
textPaint.setStyle(Paint.Style.FILL);
drawCanvas.drawText("Text", startX, startY, textPaint);
break;
}
}
// Public methods for controlling the drawing
public void setDrawingMode(DrawingMode mode) {
this.currentMode = mode;
}
public void setColor(int color) {
this.currentColor = color;
drawPaint.setColor(color);
}
public void setBrushSize(float size) {
this.brushSize = size;
drawPaint.setStrokeWidth(size);
}
public void clearCanvas() {
drawCanvas.drawColor(Color.WHITE);
drawingObjects.clear();
drawInitialContent();
invalidate();
}
public void setFillStyle(boolean fill) {
drawPaint.setStyle(fill ? Paint.Style.FILL : Paint.Style.STROKE);
}
}
Main Canvas Activity (CanvasDrawingActivity.java)
package com.example.canvasdrawing;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
public class CanvasDrawingActivity extends AppCompatActivity {
private DrawingView drawingView;
private Button btnClear, btnShapes, btnText, btnColors;
private TextView tvInfo;
private int[] colors = {Color.BLACK, Color.RED, Color.GREEN, Color.BLUE,
Color.YELLOW, Color.MAGENTA, Color.CYAN};
private String[] colorNames = {"Black", "Red", "Green", "Blue",
"Yellow", "Magenta", "Cyan"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_canvas_drawing);
initializeViews();
setupClickListeners();
updateInfo("Free Drawing Mode - Touch and drag to draw");
}
private void initializeViews() {
drawingView = findViewById(R.id.drawingView);
btnClear = findViewById(R.id.btnClear);
btnShapes = findViewById(R.id.btnShapes);
btnText = findViewById(R.id.btnText);
btnColors = findViewById(R.id.btnColors);
tvInfo = findViewById(R.id.tvInfo);
}
private void setupClickListeners() {
btnClear.setOnClickListener(v -> {
drawingView.clearCanvas();
updateInfo("Canvas cleared");
});
btnShapes.setOnClickListener(v -> showShapeSelector());
btnText.setOnClickListener(v -> selectTextMode());
btnColors.setOnClickListener(v -> showColorSelector());
}
private void showShapeSelector() {
String[] shapes = {"Free Draw", "Rectangle", "Circle", "Line"};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Select Drawing Mode");
builder.setItems(shapes, (dialog, which) -> {
switch (which) {
case 0:
drawingView.setDrawingMode(DrawingView.DrawingMode.FREE_DRAW);
updateInfo("Free Drawing Mode");
break;
case 1:
drawingView.setDrawingMode(DrawingView.DrawingMode.RECTANGLE);
updateInfo("Rectangle Mode - Touch and drag to draw rectangles");
break;
case 2:
drawingView.setDrawingMode(DrawingView.DrawingMode.CIRCLE);
updateInfo("Circle Mode - Touch and drag to draw circles");
break;
case 3:
drawingView.setDrawingMode(DrawingView.DrawingMode.LINE);
updateInfo("Line Mode - Touch and drag to draw lines");
break;
}
});
builder.show();
}
private void selectTextMode() {
drawingView.setDrawingMode(DrawingView.DrawingMode.TEXT);
updateInfo("Text Mode - Tap to place text");
Toast.makeText(this, "Tap anywhere to place text", Toast.LENGTH_SHORT).show();
}
private void showColorSelector() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Select Color");
builder.setItems(colorNames, (dialog, which) -> {
drawingView.setColor(colors[which]);
updateInfo("Color changed to " + colorNames[which]);
});
builder.show();
}
private void updateInfo(String message) {
tvInfo.setText(message);
}
}
Key Features Demonstrated
Telephony API Application Features:
- Device Information: IMEI, device ID, phone type
- Network Details: Operator, network type, signal strength
- SIM Information: SIM state, operator, subscriber details
- Real-time Updates: Phone state listener for dynamic updates
- Permission Handling: Runtime permission requests
- Error Handling: Security exceptions and permission denials
Canvas Drawing Application Features:
- Multiple Drawing Modes: Free draw, shapes, text
- Shape Drawing: Rectangle, circle, line, oval, arc
- Text Rendering: Various styles and effects
- Color Selection: Multiple color options
- Interactive Drawing: Touch event handling
- Canvas Management: Clear, redraw capabilities
- Visual Effects: Gradients, shadows, transparency
Learning Outcomes
Students will understand:
- How to access device telephony information
- Network state monitoring and updates
- Canvas drawing fundamentals
- Touch event handling for drawing
- Paint and Path usage for graphics
- Permission management in Android
- Real-time data updates in UI